package com.apestech.formwork.run;

import com.apestech.formwork.run.core.ExecDefine;
import com.apestech.formwork.run.core.ExecUtil;
import com.apestech.formwork.run.core.ExecWhileRow;
import com.apestech.formwork.xml.core.exec.SingleNode;
import com.apestech.formwork.xml.core.var.NodeVarExcute;
import com.apestech.framework.db.SqlSession;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;

import java.util.ArrayList;

/**
 * 执行过程
 *
 * @author hup
 * @create 2018-04-25-15:29
 */
public class Execution {

    private ArrayList<SingleNode> steps;
    private SqlSession session;
    private JSONObject input=new JSONObject();
    private JSONObject alldata;
    private JSONObject defineJson;
    private boolean success;
    private String error;
    private String errorId;
    private JSONArray outlist;

    public Execution(ArrayList<SingleNode> steps){
        this.steps=steps;
    }

    public void setSqlSession(SqlSession session){
        this.session=session;
    }

    public void setInput(JSONObject input){
        this.input=input;
    }

    public void execute() throws Exception {
        this.alldata=this.input;
        int len=this.steps.size();
        for(int i=0; i<len; i++){
            SingleNode node=this.steps.get(i);
            execStep(node);
            if(this.error!=null){
                break;
            }
        }
    }

    private void execStep(SingleNode node) throws Exception {
        String name=node.getName();
        if((NodeVarExcute.getDEFINE()).equals(name)){
            define(node);
        } else {
            whileNode(node, this.alldata);
        }
    }

    private void whileNode(SingleNode node, JSONObject data) throws Exception {
        String name=node.getName();
        String type=node.getType();
        String preconditions=node.getPreconditions();
        String errorMsg=node.getError();

        if(NodeVarExcute.getWHILE().equals(name) || NodeVarExcute.getPRIORITY().equals(name)){
            if("notIsEmpty".equals(preconditions)){
                if(this.defineJson.size()==0){
                    this.error=errorMsg;
                    this.errorId="EXECUTION_DEF_ERROR";
                    this.success=false;
                    return;
                }
            }
            if(NodeVarExcute.getEXECUTE().equals(type)){
                int wlen=node.getWhileList().size();
                if(wlen==0){
                    this.errorId="WHILE_EXECUTION_EMPTY";
                    this.error="没有符合条件数据";
                    this.success=false;
                }
                JSONObject in=ExecUtil.getInput(node, this.defineJson, this.session);
                JSONArray list= (JSONArray) ExecUtil.execProcess(node.getParam(), in, this, this.session);
                int len=list.size();
                if(len==0){
                    this.errorId="WHILE_EXECUTION_EMPTY";
                    this.error="没有符合条件数据";
                    this.success=false;
                }
                this.outlist=new JSONArray();
                for(int i=0; i<len; i++){
                    JSONObject map= (JSONObject) list.get(i);
                    for(int w=0; w<wlen; w++){
                        ExecWhileRow wRow=new ExecWhileRow(node.getWhileList().get(w));
                        JSONObject m=new JSONObject(this.defineJson);
                        m.putAll(this.input);
                        m.putAll(map);
                        wRow.setData(m);
                        wRow.setSqlSession(this.session);
                        wRow.expain();
                        if(!wRow.isSuccess()){
                            this.errorId=wRow.getErrorId();
                            this.error=wRow.getError();
                            this.success=false;
                            return;
                        } else {
                            if(wRow.getOutList()!=null){
                                if(wRow.getOutList().size()>0){
                                    this.outlist.add(wRow.getOutList());
                                } else {
                                    if(wRow.getOutput()!=null){
                                        this.outlist.add(wRow.getOutput());
                                    }
                                }
                            }
                        }
                    }
                    if(NodeVarExcute.getPRIORITY().equals(node.getName())){
                        break;
                    }
                }
            }
        }
        return;
    }

    private void define(SingleNode node) throws Exception {
        ExecDefine def=new ExecDefine(node);
        def.setSqlSession(this.session);
        def.setData(this.alldata);
        def.expain();
        if(def.isSuccess()){
            this.defineJson=def.getOutput();
            this.success=true;
        } else {
            this.success=false;
            this.error=def.getError();
            this.errorId=def.getErrorId();
        }
    }

    public boolean isSuccess() {
        return success;
    }

    public String getError() {
        return error;
    }

    public String getErrorId() {
        return errorId;
    }

    public JSONArray getOutlist() {
        return outlist;
    }
}
